package com.keycloak.admin.config;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.URL;
import java.net.URLEncoder;
import java.net.UnknownHostException;

/*
* 乘客端 app 支付使用
* */
public class QiFanAppConfig implements WXPayConfig {
	private byte[] certData;
	private static Logger logger = LogManager.getLogger(QiFanAppConfig.class);
	
	private static QiFanAppConfig factory = new QiFanAppConfig();
	private QiFanAppConfig() {		
	};
	public static QiFanAppConfig getFactory() {
		return factory;
	}
		
	@Override
	public String getAppID() {
		return "wx71e19b3a4361544d";
	}
		
	@Override
	public String getKey() {
		return "uaQnXaoWeiXinZinYue10D1220hiFu27";
	}

	@Override
	public String getAppSecret() {
		return "9e9bdd2dc1f7ba11c58d7814149ab2ab";
	}


	@Override
	public String getMchID() {
		return "1502479061";
	}
	
	@Override
	public InputStream getCertStream() {
		ByteArrayInputStream certBis = new ByteArrayInputStream(this.certData);
        return certBis;
	}
	public void setCertStream(ServletContext context) {
		if (this.certData!=null && this.certData.length>0){
			//already loaded
			return;
		}
		try {
			String certPath = context.getRealPath("/") + "WEB-INF/apiclient_cert.p12";
	        File file = new File(certPath);
	        InputStream certStream = new FileInputStream(file);
	        this.certData = new byte[(int) file.length()];
	        certStream.read(this.certData);
	        certStream.close();
		} catch (Exception e){
			logger.error("setCertStream error:" + e.getMessage());
		}
	}

	public String getIP() {
		String ip = "";
		InetAddress addr;
		try {
			addr = InetAddress.getLocalHost();
			ip = addr.getHostAddress();//获得本机IP
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}

		return ip;
	}




	@Override
	public int getHttpConnectTimeoutMs() {
		return 8000;
	}

	@Override
	public int getHttpReadTimeoutMs() {
		return 10000;
	}

	public String getIP(HttpServletRequest request){
		String ip = request.getHeader("x-forwarded-for");       
	    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {       
	        ip = request.getHeader("Proxy-Client-IP");       
	    }       
	    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {       
	        ip = request.getHeader("WL-Proxy-Client-IP");       
	    }       
	    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {       
	        ip = request.getRemoteAddr();       
	    }       
	    return ip;    
	}

	//上线时改主机名成 ydx ,乘客户端微信app支付异步回调
	public String getNofigyUrl(){
		return "https://ydx.yuedaowang.com/WxAppPay/SuccessNotifyX";
	}

	//上线时改主机名成 ydx ,乘客户端微信app支付异步回调
	public String getNofigyUrl4refund(){
		return "https://ydx.yuedaowang.com/WxAppRefund/SuccessNotifyX";
	}

	public String getAccessToken(ServletContext application){
		try {
			String access_token = (String) application.getAttribute("access_token");
			String refresh_token = (String) application.getAttribute("refresh_token");
			Object tokenExpire =  application.getAttribute("expires_in");
			boolean isExpire = false;
			long currentTime = System.currentTimeMillis();
			if (tokenExpire == null || (tokenExpire!=null && (long)tokenExpire< currentTime)){
				isExpire = true;
			}
			if (access_token==null || (refresh_token == null && access_token != null && isExpire)){
				//获取access_token
				//https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
				String tokenURL = "https://api.weixin.qq.com/cgi-bin/token";
				String query = String.format(
						"grant_type=client_credential&appid=%s&secret=%s",
						URLEncoder.encode(this.getAppID(), "UTF-8"),
						URLEncoder.encode(this.getKey(), "UTF-8"));
				
				URL url = new URL(tokenURL + "?" + query);
		
				InputStream is = url.openStream();
				JsonReader rdr = Json.createReader(is);
				JsonObject obj = rdr.readObject();
				rdr.close();
		
				logger.info("get new access_token result:" + obj.toString());
				
				if (obj.containsKey("errcode")){
					String errcode = obj.getString("errcode");
					String errmsg = obj.getString("errmsg");
					logger.error("getAccessToken error:" + errcode + "," + errmsg);
					return null;
				} else {
					String token = obj.getString("access_token");
					int expires_in = obj.getInt("expires_in");
					application.setAttribute("access_token", token);
					application.setAttribute("expires_in", expires_in*1000+System.currentTimeMillis());
					return token;
				}
			} else if (refresh_token != null && isExpire){
				//try refresh token first,TODO: check 30 days since last get
				//https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN 
				String tokenURL = "https://api.weixin.qq.com/sns/oauth2/refresh_token";
				String query = String.format(
						"grant_type=refresh_token&appid=%s&refresh_token=%s",
						URLEncoder.encode(this.getAppID(), "UTF-8"),
						URLEncoder.encode(refresh_token, "UTF-8"));
				
				URL url = new URL(tokenURL + "?" + query);
		
				InputStream is = url.openStream();
				JsonReader rdr = Json.createReader(is);
				JsonObject obj = rdr.readObject();
				rdr.close();
		
				logger.info("get new refresh_token result:" + obj.toString());
				
				if (obj.containsKey("errcode")){
					String errcode = obj.getString("errcode");
					String errmsg = obj.getString("errmsg");
					logger.error("get refresh_token error:" + errcode + "," + errmsg);
					return null;
				} else {
					String token = obj.getString("access_token");
					String refresh = obj.getString("refresh_token");
					int expires_in = obj.getInt("expires_in");
					application.setAttribute("access_token", token);
					application.setAttribute("refresh_token", refresh);
					application.setAttribute("expires_in", expires_in*1000+System.currentTimeMillis());
					return token;
				}
			} else {
				logger.info("access_token is still valid:" + access_token);
				return access_token;
			}
		} catch (Exception e){
			logger.error("getAccessToken exception:" + e.getMessage());
		}
		return null;
	}
	
	//这个是微信回掉时使用的方法，没有用户session
	public String getUnionID(ServletContext application, String openid){
		//获取用户基本信息（包括UnionID机制）
		//http请求方式: GET https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN 
		try {
			String access_token = this.getAccessToken(application);

			String tokenURL = "https://api.weixin.qq.com/cgi-bin/user/info";
			String query = String.format(
					"access_token=%s&openid=%s&lang=zh_CN",
					URLEncoder.encode(access_token, "UTF-8"),
					URLEncoder.encode(openid, "UTF-8"));
			
			URL url = new URL(tokenURL + "?" + query);
	
			InputStream is = url.openStream();
			JsonReader rdr = Json.createReader(is);
			JsonObject obj = rdr.readObject();
			rdr.close();
	
			logger.info("get user info result:" + obj.toString());
			
			if (obj.containsKey("errcode")){
				String errcode = obj.getString("errcode");
				String errmsg = obj.getString("errmsg");
				logger.error("getUnionID error:" + errcode + "," + errmsg);
				return openid;
			} else {				
				String unionid = obj.getString("unionid");				
				return unionid;
			}
		} catch (Exception e){
			logger.error("getUnionID exception:" + e.getMessage());
		}
		return null;
	}

	public void getUserInfo(HttpSession session, String access_token, String openid) {
		try {
			// 获取用户基本信息（包括UnionID机制）
			String userinfoUrl = "https://api.weixin.qq.com/sns/userinfo";
			String userinfoquery = String.format(
					"access_token=%s&openid=%s&lang=zh_CN",
					URLEncoder.encode(access_token, "UTF-8"),
					URLEncoder.encode(openid, "UTF-8"));

			URL fullurl = new URL(userinfoUrl + "?" + userinfoquery);

			InputStream isUI = fullurl.openStream();
			JsonReader rdrUI = Json.createReader(isUI);
			JsonObject objUI = rdrUI.readObject();
			rdrUI.close();

			logger.info("user info:" + objUI.toString());

			if (objUI.containsKey("errcode")) {
				String errcode = objUI.getString("errcode");
				String errmsg = objUI.getString("errmsg");
				logger.error("getUserInfo error:" + errcode + "," + errmsg);
			} else {
				if (objUI.containsKey("nickname")) {
					String nickname = objUI.getString("nickname");
					String headimgurl = objUI.getString("headimgurl");
					session.setAttribute("nickname", nickname);
					session.setAttribute("headimgurl", headimgurl);
				}
			}
		} catch (Exception e) {
			logger.error("getUserInfo exception:" + e.getMessage());
		}
	}
}
